#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <jsoncpp/json/json.h>

namespace Protocol
{
#define MYSELF 0

#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define SEP "\r\n"
#define SEP_LEN strlen(SEP)

#define DIVZERO 1
#define MODZERO 2
#define ILLEGAL 3

    class Request
    {
    public:
        Request()
        {
        }

        Request(int left, int right, char op)
            : _left(left),
              _right(right),
              _op(op)
        {
        }

        ~Request() {}

        std::string Serialize()
        {
#ifdef MYSELF
            //"left _op _right"
            std::string str;
            str = std::to_string(_left);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_right);
            return str;
#else
            //创建并序列化一个JSON对象
            Json::Value root;
            root["left"] = _left;
            root["right"] = _right;
            root["op"] = _op;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }

        bool Deserialize(const std::string &str)
        {
#ifdef MYSELF
            //"left _op _right"
            std::size_t firstSpace = str.find(SPACE);
            if (firstSpace == std::string::npos)
                return false;

            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
                return false;

            _left = atoi(str.substr(0, firstSpace).c_str());
            _right = atoi(str.substr(right + SPACE_LEN).c_str());

           if (firstSpace + SPACE_LEN > str.size())
                return false;
            else
                _op = str[firstSpace + SPACE_LEN];

            return true;
#else
            //解析一个JSON字符串并提取值
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);
            _left = root["left"].asInt();
            _right = root["right"].asInt();
            _op = root["op"].asInt();

            return true;
#endif
        }

    public:
        int _left;
        int _right;
        char _op;
    };

    class Response
    {
    public:
        Response()
        {
        }
        Response(int result, int code, int left, int right, char op)
            : _result(result),
              _code(code),
              _left(left),
              _right(right),
              _op(op)
        {
        }
        ~Response() {}

        // "_code result_"
        std::string Serialize()
        {
#ifdef MYSELF
            std::string s;
            s = std::to_string(_code);
            s += SPACE;
            s += std::to_string(_result);

            return s;
#else
            Json::Value root;
            root["code"] = _code;
            root["result"] = _result;
            root["xx"] = _left;
            root["yy"] = _right;
            root["zz"] = _op;
            Json::FastWriter writer;
            return writer.write(root);
#endif
        }
        // "_code result_"
        bool Deserialize(const std::string &s)
        {
#ifdef MYSELF
            std::size_t pos = s.find(SPACE);
            if (pos == std::string::npos)
                return false;

            _code = atoi(s.substr(0, pos).c_str());
            _result = atoi(s.substr(pos + SPACE_LEN).c_str());
            return true;
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(s, root);
            _code = root["code"].asInt();
            _result = root["result"].asInt();
            _left = root["xx"].asInt();
            _right = root["yy"].asInt();
            _op = root["zz"].asInt();
            return true;
#endif
        }

    public:
        int _result;
        int _code;

        //一下成员变量实际上不用 此处为了测试JSON比自定义协议更容易扩展
        int _left;
        int _right;
        char _op;
    };

    bool Recv(int socket, std::string *out)
    {
        // UDP是面向数据报, TCP 面向字节流的
        // recv不能保证读到的inbuffer是一个完整的请求 对协议进一步定制

        char buffer[1024];
        ssize_t s = recv(socket, buffer, sizeof(buffer) - 1, 0);
        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if (s == 0)
        {
            // std::cout << "client quit" << std::endl;
            return false;
        }
        else
        {
            // std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }

    void Send(int socket, const std::string str)
    {
        // std::cout << "sent in" << std::endl;
        int sendBytes = send(socket, str.c_str(), str.size(), 0);
        // if (sendBytes < 0)
        //    std::cout << "send error" << std::endl;
    }

    // "length\r\nXXXXXX\r\n"
    std::string Encode(std::string &s)
    {
        std::string new_package = std::to_string(s.size());
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }

    // "length\r\n_left _op _right\r\n"
    std::string Decode(std::string &buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if (pos == std::string::npos)
            return "";

        int length = atoi(buffer.substr(0, pos).c_str());
        int surplus = buffer.size() - pos - 2 * SEP_LEN;

        if (surplus < length)
            return "";

        // 至少具有一个完整的报文
        buffer.erase(0, pos + SEP_LEN);
        std::string msg = buffer.substr(0, length);
        buffer.erase(0, length + SEP_LEN);

        return msg;
    }
}